using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using Sfs2X;
using Sfs2X.Core;
using Sfs2X.Entities;
using Sfs2X.Requests;
using Sfs2X.Logging;
using Sfs2X.Entities.Data;

public class LoginGUI : MonoBehaviour
{
	public enum AccountStates{NoAccount, GuestAccount, UserAccount}
	
	private SmartFox mSmartFox;
	private bool mSFSDebug = true;	
	private bool mShuttingDown = false;
	private AccountStates mAccountState = AccountStates.NoAccount;
	
	public string serverName = "127.0.0.1";
	public int serverPort = 9339;
	public string zone = "Demo";
	
	
	private string mUserName = "";
	private string mPassword = "";
	private string loginErrorMessage = "";

	/************
     * Unity callback methods
     ************/

	void OnApplicationQuit ()
	{
		mShuttingDown = true;
	}
	
	void FixedUpdate ()
	{
		mSmartFox.ProcessEvents ();
	}
	
	void Awake ()
	{
		Application.runInBackground = true;

		// In a webplayer (or editor in webplayer mode) we need to setup security policy negotiation with the server first
		if (Application.isWebPlayer || Application.isEditor) {
			if (!Security.PrefetchSocketPolicy (serverName, serverPort, 500)) {
				Debug.LogError ("Security Exception. Policy file load failed!");
			}
		}		

		if (SmartFoxConnection.IsInitialized) {
			mSmartFox = SmartFoxConnection.Connection;
		} else {
			mSmartFox = new SmartFox (mSFSDebug);
		}

		// Register callback delegate
		mSmartFox.AddEventListener (SFSEvent.CONNECTION, OnConnection);
		mSmartFox.AddEventListener (SFSEvent.CONNECTION_LOST, OnConnectionLost);
		mSmartFox.AddEventListener (SFSEvent.LOGIN, OnLogin);
		mSmartFox.AddEventListener (SFSEvent.LOGIN_ERROR, OnLoginError);
		
		mSmartFox.AddLogListener (LogLevel.DEBUG, OnDebugMessage);

		mSmartFox.Connect (serverName, serverPort);
		
		if(PlayerPrefs.HasKey("name") && PlayerPrefs.HasKey("password"))
		{
			mUserName = PlayerPrefs.GetString("name");
			mPassword = PlayerPrefs.GetString("password");
			//check if the username is "guest_xxxx" format
			if(mUserName.Contains("guest"))
				mAccountState = AccountStates.GuestAccount;
			else
				mAccountState = AccountStates.UserAccount;
		}
		else
		{
			mAccountState = AccountStates.NoAccount;
		}
	}

	void OnGUI ()
	{
		// Determine which state we are in and show the GUI accordingly
		if(mSmartFox.IsConnected) {
				DrawLoginGUI();
		} else {
			string message = "Waiting for connection";
			if (loginErrorMessage != "") {
				message = "Connection error. " + loginErrorMessage;
			}
			DrawMessagePanelGUI(message);
		}
	}
	
	/************
	 * GUI methods
	 ************/
	
	// Generic single message panel
	void DrawMessagePanelGUI (string message)
	{
		// Lets just quickly set up some GUI layout variables
		float panelWidth = 400;
		float panelHeight = 300;
		float panelPosX = Screen.width / 2 - panelWidth / 2;
		float panelPosY = Screen.height / 2 - panelHeight / 2;
		
		// Draw the box
		GUILayout.BeginArea (new Rect (panelPosX, panelPosY, panelWidth, panelHeight));
		GUILayout.Box ("Demo Error", GUILayout.ExpandWidth (true), GUILayout.ExpandHeight (true));
		GUILayout.BeginVertical ();
		GUILayout.BeginArea (new Rect (20, 25, panelWidth - 40, panelHeight - 60), GUI.skin.customStyles [0]);
		
		// Center label
		GUILayout.BeginHorizontal ();
		GUILayout.FlexibleSpace ();
		GUILayout.BeginVertical ();
		GUILayout.FlexibleSpace ();
			
		GUILayout.Label (message);
			
		GUILayout.FlexibleSpace ();
		GUILayout.EndVertical ();
		GUILayout.FlexibleSpace ();
		GUILayout.EndHorizontal ();
		
		GUILayout.EndArea ();		
			
		GUILayout.EndVertical ();
		GUILayout.EndArea ();		
	}
	
	// Login GUI allowing for username, password and zone selection
	private void DrawLoginGUI()
	{
		// Lets just quickly set up some GUI layout variables
		float panelWidth = 400;
		float panelHeight = 300;
		float panelPosX = Screen.width / 2 - panelWidth / 2;
		float panelPosY = Screen.height / 2 - panelHeight / 2;
		
		// Draw the box
		GUILayout.BeginArea (new Rect (panelPosX, panelPosY, panelWidth, panelHeight));
		GUILayout.Box ("Demo Login", GUILayout.ExpandWidth (true), GUILayout.ExpandHeight (true));
		GUILayout.BeginVertical ();
		GUILayout.BeginArea (new Rect (20, 25, panelWidth - 40, panelHeight - 60), GUI.skin.customStyles [0]);
		
		// Lets show login box!
		GUILayout.FlexibleSpace ();
				
		GUILayout.BeginHorizontal ();
		GUILayout.Label ("Username:");
		mUserName = GUILayout.TextField (mUserName, 25, GUILayout.MinWidth (200));
		GUILayout.EndHorizontal ();

		GUILayout.BeginHorizontal ();
		GUILayout.Label ("Password:");
		mPassword = GUILayout.TextField (mPassword, 25, GUILayout.MinWidth (200));
		GUILayout.EndHorizontal ();		
		
		GUILayout.Label (loginErrorMessage);
			
		// Center login button
		GUILayout.BeginHorizontal ();
		GUILayout.FlexibleSpace ();		
		if (GUILayout.Button ("Login") || (Event.current.type == EventType.keyDown && Event.current.character == '\n')) {
			Debug.Log ("Sending login request");
			mSmartFox.Send(new LoginRequest (mUserName, mPassword, "Demo"));
		}
		GUILayout.FlexibleSpace ();
		if (GUILayout.Button ("Create New Account")) {
			mSmartFox.Send (new LoginRequest (null, null, "Demo"));	
			Debug.Log ("Entering Create Account GUI");
		}		
		GUILayout.EndHorizontal ();
		GUILayout.FlexibleSpace ();
		
		GUILayout.EndArea ();
				
		GUILayout.EndVertical ();
		GUILayout.EndArea ();
	}
	


	/************
	 * Helper methods
	 ************/

	private void UnregisterSFSSceneCallbacks ()
	{
		// This should be called when switching scenes, so callbacks from the backend do not trigger code in this scene
		mSmartFox.RemoveAllEventListeners ();
	}

	/************
	 * Callbacks from the SFS API
	 ************/

	public void OnConnection (BaseEvent evt)
	{
		bool success = (bool)evt.Params ["success"];
		string error = (string)evt.Params ["error"];
		
		Debug.Log ("On Connection callback got: " + success + " (error : <" + error + ">)");
		
		loginErrorMessage = "";
		if (success) {
			SmartFoxConnection.Connection = mSmartFox;
		} else {
			loginErrorMessage = error;
		}
	}

	public void OnConnectionLost (BaseEvent evt)
	{
		loginErrorMessage = "Connection lost / no connection to server";
		UnregisterSFSSceneCallbacks ();
	}

	public void OnDebugMessage (BaseEvent evt)
	{
		string message = (string)evt.Params ["message"];
		Debug.Log ("[SFS DEBUG] " + message);
	}

	public void OnLogin (BaseEvent evt)
	{
		// On to the lobby
		loginErrorMessage = "";
		UnregisterSFSSceneCallbacks ();		
		Application.LoadLevel ("Lobby");
		
		// On to the limbo room
		
		Debug.Log ("Entering Create Account GUI");	
	}
	
	public void OnLoginError (BaseEvent evt)
	{
		// Login failed - lets display the error message sent to us
		loginErrorMessage = (string)evt.Params ["errorMessage"];
		Debug.Log ("Login error: " + loginErrorMessage);			
	}
}